package com.cloudcc.cloudframe.ui.viewgroup.loadmore;

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.AbsListView;
import android.widget.LinearLayout;

/**
 * @author huqiu.lhq
 */
public abstract class LoadMoreContainerBase extends LinearLayout implements
		LoadMoreContainer {

	private AbsListView.OnScrollListener mOnScrollListener;
	private LoadMoreUIHandler mLoadMoreUIHandler;
	private LoadMoreHandler mLoadMoreHandler;

	private boolean mIsLoading;// 是否正在加载。。
	private boolean mHasMore = false;// 是否还有更多
	private boolean mAutoLoadMore = true;// 是否自动加载更多
	private boolean mLoadError = false;// 是否是加载错误

	private boolean mListEmpty = true;// 是不是空
	private boolean mShowLoadingForFirstPage = false;
	private View mFooterView;// footerview

	private AbsListView mAbsListView;
	private int offsetSize = 1;

	public LoadMoreContainerBase(Context context) {
		super(context);
	}

	public LoadMoreContainerBase(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	@Override
	protected void onFinishInflate() {
		super.onFinishInflate();
		mAbsListView = retrieveAbsListView();
		init();
	}

	/**
	 * @deprecated It's totally wrong. Use {@link #useDefaultFooter} instead.
	 */
	@Deprecated
	public void useDefaultHeader() {
		useDefaultFooter();
	}

	public void useDefaultFooter() {
		LoadMoreDefaultFooterView footerView = new LoadMoreDefaultFooterView(
				getContext());
		footerView.setVisibility(GONE);
		setLoadMoreView(footerView);
		setLoadMoreUIHandler(footerView);
	}

	private void init() {

		if (mFooterView != null) {
			addFooterView(mFooterView);
		}

		mAbsListView.setOnScrollListener(new AbsListView.OnScrollListener() {

			private boolean mIsEnd = false;

			@Override
			public void onScrollStateChanged(AbsListView view, int scrollState) {

				if (null != mOnScrollListener) {
					mOnScrollListener.onScrollStateChanged(view, scrollState);
				}
				if (scrollState == SCROLL_STATE_IDLE) {
					if (mIsEnd) {
						onReachBottom();
					}
				}
			}

			@Override
			public void onScroll(AbsListView view, int firstVisibleItem,
					int visibleItemCount, int totalItemCount) {
				if (null != mOnScrollListener) {
					mOnScrollListener.onScroll(view, firstVisibleItem,
							visibleItemCount, totalItemCount);
				}
				if (firstVisibleItem + visibleItemCount >= totalItemCount
						- offsetSize) {
					mIsEnd = true;
				} else {
					mIsEnd = false;
				}
			}
		});
	}

	private void tryToPerformLoadMore() {
		if (mIsLoading) {
			return;
		}

		// no more content and also not load for first page
		if (!mHasMore && !(mListEmpty && mShowLoadingForFirstPage)) {
			return;
		}

		mIsLoading = true;

		if (mLoadMoreUIHandler != null) {
			mLoadMoreUIHandler.onLoading(this);
		}
		if (null != mLoadMoreHandler) {
			mLoadMoreHandler.onLoadMore(this);
		}
	}

	private void onReachBottom() {
		// if has error, just leave what it should be
		if (mLoadError) {
			return;
		}
		if (mAutoLoadMore) {
			tryToPerformLoadMore();
		} else {
			if (mHasMore) {
				mLoadMoreUIHandler.onWaitToLoadMore(this);
			}
		}
	}

	@Override
	public void setShowLoadingForFirstPage(boolean showLoading) {
		mShowLoadingForFirstPage = showLoading;
	}

	@Override
	public void setAutoLoadMore(boolean autoLoadMore) {
		mAutoLoadMore = autoLoadMore;
	}

	@Override
	public void setOnScrollListener(AbsListView.OnScrollListener l) {
		mOnScrollListener = l;
	}

	@Override
	public void setLoadMoreView(View view) {
		// has not been initialized
		if (mAbsListView == null) {
			mFooterView = view;
			return;
		}
		// remove previous
		if (mFooterView != null && mFooterView != view) {
			removeFooterView(view);
		}

		// add current
		mFooterView = view;
		mFooterView.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View view) {
				tryToPerformLoadMore();
			}
		});

		addFooterView(view);
	}

	@Override
	public void setLoadMoreUIHandler(LoadMoreUIHandler handler) {
		mLoadMoreUIHandler = handler;
	}

	@Override
	public void setLoadMoreHandler(LoadMoreHandler handler) {
		mLoadMoreHandler = handler;
	}

	/**
	 * page has loaded
	 * 
	 * @param emptyResult
	 * @param hasMore
	 */
	@Override
	public void loadMoreFinish(boolean emptyResult, boolean hasMore) {
		mLoadError = false;
		mListEmpty = emptyResult;
		mIsLoading = false;
		mHasMore = hasMore;

		if (mLoadMoreUIHandler != null) {
			mLoadMoreUIHandler.onLoadFinish(this, emptyResult, hasMore);
		}
	}

	@Override
	public void loadMoreError(int errorCode, String errorMessage) {
		mIsLoading = false;
		mLoadError = true;
		if (mLoadMoreUIHandler != null) {
			mLoadMoreUIHandler.onLoadError(this, errorCode, errorMessage);
		}
	}

	public int getOffsetSize() {
		return offsetSize;
	}

	public void setOffsetSize(int offsetSize) {
		this.offsetSize = offsetSize;
	}

	protected abstract void addFooterView(View view);

	protected abstract void removeFooterView(View view);

	protected abstract AbsListView retrieveAbsListView();
}